Ejemplo modelo de puntos referenciados

Autor/a

Jorge de la Vega

Fecha de publicación

5 de junio de 2024

Examples with simmer

library(simmer)
library(simmer.plot)

Simpler example: one server and many clients arriving at random

Consider a single server with service time N(10,4) and clients have interarrival times exp(1/5) (one client every five minutes)

client <- 
  trajectory("Client") %>% 
  #log_("Here I am") %>%   # can send a message for each arrive
  seize("server") %>%
  timeout(function() rnorm(1,10,2)) %>% # service time
  release("server") # %>%
  #log_("Finished")

shop <- 
  simmer("shop") %>%   #initializes a simulation environment
  add_resource("server", 1) %>%
  add_generator("Client", client, function() rexp(1,1/5))

# Run a replication 100 minutes. 
shop %>% run(until  = 100)
simmer environment: shop | now: 100 | next: 101.673684204213
{ Monitor: in memory }
{ Resource: server | monitored: TRUE | server status: 1(1) | queue status: 10(Inf) }
{ Source: Client | monitored: 1 | n_generated: 20 }
# Monitor arrivals of clients, and compute the waiting time in queue
# activity_time is service time. 
shop %>% 
  get_mon_arrivals() %>%
  transform(waiting_time = end_time -start_time - activity_time)
     name start_time end_time activity_time finished replication  waiting_time
1 Client0   2.463082 12.68849     10.225405     TRUE           1 -1.776357e-15
2 Client1  12.964034 22.12465      9.160620     TRUE           1  1.776357e-15
3 Client2  18.093027 34.38824     12.263582     TRUE           1  4.031627e+00
4 Client3  25.837158 41.90508      7.516842     TRUE           1  8.551077e+00
5 Client4  31.499937 54.04382     12.138744     TRUE           1  1.040514e+01
6 Client5  38.826483 66.59546     12.551642     TRUE           1  1.521734e+01
7 Client6  41.492093 81.92253     15.327064     TRUE           1  2.510337e+01
8 Client7  46.588726 93.26013     11.337601     TRUE           1  3.533380e+01
# Monitor server
shop %>% get_mon_resources()
   resource      time server queue capacity queue_size system limit replication
1    server  2.463082      1     0        1        Inf      1   Inf           1
2    server 12.688487      0     0        1        Inf      0   Inf           1
3    server 12.964034      1     0        1        Inf      1   Inf           1
4    server 18.093027      1     1        1        Inf      2   Inf           1
5    server 22.124654      1     0        1        Inf      1   Inf           1
6    server 25.837158      1     1        1        Inf      2   Inf           1
7    server 31.499937      1     2        1        Inf      3   Inf           1
8    server 34.388236      1     1        1        Inf      2   Inf           1
9    server 38.826483      1     2        1        Inf      3   Inf           1
10   server 41.492093      1     3        1        Inf      4   Inf           1
11   server 41.905077      1     2        1        Inf      3   Inf           1
12   server 46.588726      1     3        1        Inf      4   Inf           1
13   server 49.898850      1     4        1        Inf      5   Inf           1
14   server 50.328328      1     5        1        Inf      6   Inf           1
15   server 54.043821      1     4        1        Inf      5   Inf           1
16   server 56.358919      1     5        1        Inf      6   Inf           1
17   server 66.595463      1     4        1        Inf      5   Inf           1
18   server 66.864360      1     5        1        Inf      6   Inf           1
19   server 70.328969      1     6        1        Inf      7   Inf           1
20   server 71.395474      1     7        1        Inf      8   Inf           1
21   server 81.922527      1     6        1        Inf      7   Inf           1
22   server 86.772002      1     7        1        Inf      8   Inf           1
23   server 88.489641      1     8        1        Inf      9   Inf           1
24   server 89.081534      1     9        1        Inf     10   Inf           1
25   server 93.107387      1    10        1        Inf     11   Inf           1
26   server 93.260128      1     9        1        Inf     10   Inf           1
27   server 95.516017      1    10        1        Inf     11   Inf           1
# Monitoring the process
resources <- get_mon_resources(shop)
plot(resources, metric = "utilization")

plot(resources, metric = "usage", steps = T)

Replications of the simulations

Simulate the process for 8 hrs (8*60 = 480 minutes) and replicate 100 times

# simulate 8 hours 100 times
envs <- lapply(1:100, 
               function(i) {
                simmer("shop") %>% 
                add_resource("server",1) %>%
                add_generator("Client", client, function() rexp(1, 1/5)) %>%
                run(until = 480)})

We can obtain performance metrics from the runs

plot(get_mon_resources(envs), metric = "utilization")

plot(get_mon_resources(envs), metric = "usage", items = "server")

plot(get_mon_arrivals(envs), metric = "waiting_time")
`geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

Consider adding a total of three servers

# simulate 8 hours 100 times
envs <- lapply(1:100, 
               function(i) {
                simmer("shop") %>% 
                add_resource("server",3) %>%
                add_generator("Client", client, function() rexp(1, 1/5)) %>%
                run(until = 480)})
plot(get_mon_resources(envs), metric = "utilization")

# number of servers busy during the day 
plot(get_mon_resources(envs), metric = "usage", items = "server")

# number of clients waiting for service
plot(get_mon_resources(envs), metric = "usage", items = "queue")

# waiting time
plot(get_mon_arrivals(envs),  metric = "waiting_time")
`geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

Several counters with individual queues

Each counter is assumed to have its own queue. Each client has to decide which queue to join, usually decides to join the shortest queue. There are several policies that can be considered

  • shortest-queue: the resource selects the shortest queue
  • round-robin: resources will be selected in a cyclical nature
  • first-available: the first available resource is selected
  • random: a resource is randomly selected
client <-
  trajectory("Client") %>%
  select(c("server1", "server2"), policy = "shortest-queue") %>%
  seize_selected() %>%
  timeout(function() rnorm(1,10,4)) %>%
  release_selected() 

shop <-
  simmer("shop") %>%
  add_resource("server1", 1) %>%
  add_resource("server2", 1) %>%
  add_generator("Client", client, function() rexp(1, 1/5))

run(shop, until = 240)
simmer environment: shop | now: 240 | next: 249.35399741207
{ Monitor: in memory }
{ Resource: server1 | monitored: TRUE | server status: 1(1) | queue status: 0(Inf) }
{ Resource: server2 | monitored: TRUE | server status: 1(1) | queue status: 0(Inf) }
{ Source: Client | monitored: 1 | n_generated: 45 }
# Monitoring the process
resources <- get_mon_resources(shop)
plot(resources, metric = "utilization")

plot(resources, metric = "usage", steps = T)

Simulate a ambulatory consultation service

First a patient is seen by a nurse for preliminary steps. Then the patient is seen by two doctors for the consultation and finally by administrative staff to schedule a follow-up appointment or other tasks.

Construct a patient trajectory defining the previous steps

patient <- trajectory("patients") %>% 
           ## add nurse 
           seize("nurse",1) %>% 
           timeout(function() rnorm(1, 15)) %>%
           release("nurse", 1) %>%
           ## add a consultation activity
           seize("doctor", 2) %>%
           timeout(function() rnorm(1, 20)) %>%
           release("doctor", 2) %>%
           ## add a planning activity
           seize("admin", 1) %>%
           timeout(function() rnorm(1, 5)) %>%
           release("admin", 1)

plot(patient)  

Now attach arrivals and define the resources needed with capacities

envs <- lapply(1:100, function(i) {
          simmer("health center") %>%
          add_resource("nurse", 3) %>%
          add_resource("doctor", 4) %>%
          add_resource("admin", 2) %>%
          add_generator("patient", patient, function() rexp(1, 1/5)) %>%
          run(until=480)})
plot(get_mon_resources(envs), metric = "utilization")

plot(get_mon_resources(envs), metric = "usage", items = "server")

plot(get_mon_arrivals(envs), metric = "waiting_time")
`geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'